package com.zl.autocode.controller.generator;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.zl.autocode.common.constant.AutocodeConfigC;
import com.zl.autocode.common.constant.AutocodeProperties;
import com.zl.autocode.common.utils.ddl.DdlObj;
import com.zl.autocode.common.utils.ddl.DdlUtil;
import com.zl.autocode.common.utils.generator.IReaderData;
import com.zl.autocode.common.utils.generator.ZLGenerator;
import com.zl.autocode.common.utils.generator.ZLGeneratorEnum;
import com.zl.autocode.common.utils.generator.model.CfgConfig;
import com.zl.autocode.common.utils.generator.model.CfgMethodEntity;
import com.zl.autocode.common.utils.generator.model.ConvertColumn;
import com.zl.autocode.common.utils.generator.model.ConvertConfig;
import com.zl.autocode.common.utils.generator.model.ConvertTable;
import com.zl.autocode.controller.base.AutocodeBaseController;
import com.zl.autocode.dto.generator.ReqCodeGenereatorDTO;
import com.zl.autocode.dto.generator.ReqExpoerProjectDdlDTO;
import com.zl.autocode.dto.generator.ReqGetFirstTemplateOtherDTO;
import com.zl.autocode.dto.generator.ReqInitComponentTableDTO;
import com.zl.autocode.dto.generator.ReqLoadTableDTO;
import com.zl.autocode.dto.generator.ReqLoadTemplateDTO;
import com.zl.autocode.dto.generator.ReqOtherTemplateDTO;
import com.zl.autocode.dto.generator.ReqPreviewHtmlDTO;
import com.zl.autocode.dto.generator.ReqProjectFileDTO;
import com.zl.autocode.dto.generator.ReqTemplateContentDTO;
import com.zl.autocode.dto.generator.ReqUploadProjectDTO;
import com.zl.autocode.dto.generator.ResCodeGenereatorDTO;
import com.zl.autocode.dto.generator.ResLoadTableDTO;
import com.zl.autocode.dto.generator.ResLoadTemplateDTO;
import com.zl.autocode.dto.generator.ResOtherTemplateDTO;
import com.zl.autocode.dto.generator.ResPreviewHtmlDTO;
import com.zl.autocode.dto.generator.ResProjectFileDTO;
import com.zl.autocode.dto.generator.ResTemplateContentDTO;
import com.zl.autocode.dto.generator.ResTemplateParamsDTO;
import com.zl.autocode.dto.generator.ResUploadProjectDTO;
import com.zl.autocode.dto.generator.TemplateDtlVO;
import com.zl.autocode.dto.generator.CodeGenereatorDTO.FileListDTO;
import com.zl.autocode.dto.generator.TemplateDTO.TemplateParamsVO;
import com.zl.autocode.entity.autocode.ZlDdlTemplate;
import com.zl.autocode.entity.autocode.ZlDictDtl;
import com.zl.autocode.entity.autocode.ZlPreviewTemplate;
import com.zl.autocode.entity.autocode.ZlProject;
import com.zl.autocode.entity.autocode.ZlTable;
import com.zl.autocode.entity.autocode.ZlTableColumn;
import com.zl.autocode.entity.autocode.ZlTemplate;
import com.zl.autocode.entity.autocode.ZlTemplateDtl;
import com.zl.autocode.entity.autocode.ZlWebComponent;
import com.zl.autocode.entity.autocode.po.ZLCfgGenerateDtlVo;
import com.zl.autocode.entity.autocode.po.ZLCfgGenerateVo;
import com.zl.autocode.service.base.AutocodeBaseManager;
import com.zl.autocode.service.generator.IGeneratorSelectService;
import com.zl.autocode.service.generator.IGeneratorService;
import com.zl.common.aop.LogSimpleResult;
import com.zl.common.dto.ReqDTO;
import com.zl.common.dto.ResDTO;
import com.zl.common.enums.resp.GlobalRespEnum;
import com.zl.common.exception.BizException;
import com.zl.common.utils.FreemarkerTool;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONUtil;


/**
 * 生成代码
 */
@Controller("autocodeGeneratorController")
@RequestMapping("/autocode/")
public class GeneratorController extends AutocodeBaseController {
    protected final Logger LOGGER = LoggerFactory.getLogger(GeneratorController.class);
    
    private static Pattern RULE = Pattern.compile("(\\[.*?\\])");//截取条件
    
    @Autowired
    private IGeneratorService generatorService;
    @Autowired
    private Map<String,IReaderData<ConvertConfig>> readerMap;
    @Autowired
    private IGeneratorSelectService generatorSelectService;
    @Autowired
    private AutocodeProperties autocodeProperties;
    
    /**
     * 同步表数据
     **/
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value= "/loadTable", method = RequestMethod.POST)
    public ResDTO<ResLoadTableDTO> autocodeLoadtable(@RequestBody ReqDTO<ReqLoadTableDTO> reqInfo) throws Exception {
        ReqLoadTableDTO reqData = reqInfo.getReqData();
        ResLoadTableDTO resDTO = new ResLoadTableDTO();
        
        //配置
        ConvertConfig iConfig = new ConvertConfig();
        iConfig.setQueryType(reqData.getQueryType());
        iConfig.setLoadSourceType(reqData.getLoadSourceType());
        iConfig.setLoadTables(StrUtil.splitTrim(reqData.getLoadTables(), ","));
        iConfig.setLoadSeqs(StrUtil.splitTrim(reqData.getLoadSeqs(), ","));
        iConfig.setProjectId(reqData.getProjectId());
        iConfig.setLoadType(reqData.getLoadType());
        
        //查询基本设置
        generatorService.queryProjectTableConfig(reqInfo, iConfig);
        
        if(("database".equals(iConfig.getLoadType()) && StringUtils.isBlank(iConfig.getJdbcUrl())) 
               && ("pdm".equals(iConfig.getLoadType()) && StringUtils.isBlank(iConfig.getPdmPath()))
               && (StringUtils.isBlank(iConfig.getSqlPath()))){
            throw new BizException(GlobalRespEnum.MISSING_FILE);
        }
       
        if(readerMap.get(iConfig.getLoadType()+AutocodeConfigC.GENERATOR_READER_KEY) == null){
            LOGGER.info("未实现当前数据库或文件解析接口");
            throw new BizException(GlobalRespEnum.METHOD_NOT_IMPLEMENTED);
        }
        if(StringUtils.isNotBlank(reqData.getFilename())) {
            iConfig.setPdmPath(handlerRootPath(iConfig.getPdmPath())+reqData.getFilename());
        }else {
            iConfig.setPdmPath(handlerRootPath(iConfig.getPdmPath()));
            iConfig.setSqlPath(handlerRootPath(iConfig.getSqlPath()));
        }
        
        readerMap.get(iConfig.getLoadType()+AutocodeConfigC.GENERATOR_READER_KEY).parseData(iConfig);
        if("database".equals(iConfig.getLoadType()) || "pdm".equals(iConfig.getLoadType()) || "sql".equals(iConfig.getLoadType())){
            //同步表
            resDTO = generatorService.doInitialTables(reqInfo,iConfig);
        }else{
            //自定义解析方式
            resDTO = generatorService.doInitialTablesByEntity(reqInfo,iConfig);
        }
        
        return successDATA(resDTO);
    }
    
    /**
     * 传项目文件
     * @param reqInfo
     * @param fileObj
     * @return
     * @throws Exception
     */
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value = "/uploadProjectFile", method = RequestMethod.POST)
    public ResDTO<ResUploadProjectDTO> autocodeUploadProjectFile(ReqUploadProjectDTO reqInfo , MultipartFile fileObj) throws Exception {
        ResUploadProjectDTO resDTO = new ResUploadProjectDTO();
        
        if(fileObj==null || fileObj.isEmpty() || StringUtils.isBlank(autocodeProperties.getAutocodePathMajor())){
            throw new BizException(GlobalRespEnum.MISSING_FILE);
        }
        String fileExt = FileUtil.extName(fileObj.getResource().getFilename());
        if(!"zip".equalsIgnoreCase(fileExt)  && !"pdm".equalsIgnoreCase(fileExt) && !"txt".equalsIgnoreCase(fileExt) && !"java".equalsIgnoreCase(fileExt)
                && !"sql".equalsIgnoreCase(fileExt)){
            throw new BizException(GlobalRespEnum.MISSING_FILE);
        }
        
        String separatorStr = File.separator;
        
        boolean pdmFlag = "1".equals(reqInfo.getFileType())? true : false;
        
        ZlProject projectRecord = generatorSelectService.queryProject(reqInfo.getProjectId());
        
        String path = pdmFlag?projectRecord.getPdmPath() : projectRecord.getSqlPath();
        
        //不能丢失目录，否则会会删除目录下的文件
        if(StringUtils.isBlank(path)){
            throw new BizException(GlobalRespEnum.MISSING_FILE);
        }
        path=handlerRootPath(path);
        if("zip".equalsIgnoreCase(fileExt)){
            File newFile = new File(path);
            if(newFile.exists() && newFile.isDirectory()){
                FileUtil.clean(newFile);
            }
            ZipUtil.unzip(fileObj.getInputStream(),newFile,CharsetUtil.CHARSET_UTF_8);
        }else{
            //放到指定文件
            if(!path.endsWith("\\") && !path.endsWith("/")){
                path = path + separatorStr;
            }
            FileUtil.writeFromStream(fileObj.getInputStream(), path +fileObj.getOriginalFilename());
        }
        if(pdmFlag) {
            resDTO.setFilename(fileObj.getOriginalFilename());
        }
        
        return successDATA(resDTO);
    }
    
    
    /**
     * 传模板文件
     * @param reqInfo
     * @param fileObj
     * @return
     * @throws Exception
     */
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value = "/uploadTemplate", method = RequestMethod.POST)
    public ResDTO<ResLoadTemplateDTO> autocodeUploadTemplateFile(ReqLoadTemplateDTO reqInfo , MultipartFile fileObj) throws Exception {
        ResLoadTemplateDTO resDTO = new ResLoadTemplateDTO();
        
        if(fileObj==null || fileObj.isEmpty() || StringUtils.isBlank(autocodeProperties.getAutocodePathMajor())){
            throw new BizException(GlobalRespEnum.MISSING_FILE);
        }
        
        String fileExt = FileUtil.extName(fileObj.getResource().getFilename());
        if(!"zip".equalsIgnoreCase(fileExt) && !"btl".equalsIgnoreCase(fileExt) && !"vtl".equalsIgnoreCase(fileExt) && !"ftl".equalsIgnoreCase(fileExt)
                && !"ejy".equalsIgnoreCase(fileExt) && !"vm".equalsIgnoreCase(fileExt)){
            throw new BizException(GlobalRespEnum.MISSING_FILE);
        }
        
        ZlTemplate tmpleteRecord = generatorSelectService.queryTemplate(reqInfo.getTemplateId());
        
        String separatorStr = File.separator;
        String path = tmpleteRecord.getTemplatePath();
        
        //不能丢失目录，否则会会删除目录下的文件
        if(StringUtils.isBlank(path)){
            throw new BizException(GlobalRespEnum.MISSING_FILE);
        }
        path=handlerRootPath(path);
        if("zip".equalsIgnoreCase(fileExt)){
            File newFile = new File(path);
            if(newFile.exists() && newFile.isDirectory()){
                FileUtil.clean(newFile);
            }
            ZipUtil.unzip(fileObj.getInputStream(),newFile,CharsetUtil.CHARSET_UTF_8);
        }else{
            //放到指定文件
            if(!path.endsWith("\\") && !path.endsWith("/")){
                path = path + separatorStr;
            }
            FileUtil.writeFromStream(fileObj.getInputStream(), path +fileObj.getOriginalFilename());
        }
        
        return successDATA(resDTO);
    }
    /**
     * 同步模板
     **/
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value = "/loadTemplate", method = RequestMethod.POST)
    public ResDTO<ResLoadTemplateDTO> autocodeLoadTemplate(@RequestBody ReqDTO<ReqLoadTemplateDTO> reqInfo) throws Exception {
        ReqLoadTemplateDTO reqData = reqInfo.getReqData();
        ResLoadTemplateDTO resDTO = new ResLoadTemplateDTO();
        ZlTemplate tmpleteRecord = generatorSelectService.queryTemplate(reqData.getTemplateId());
        
        List<TemplateDtlVO> templateDtlList = new ArrayList<>();
        if(StringUtils.isNotBlank(tmpleteRecord.getTemplatePath())){
        	tmpleteRecord.setTemplatePath(handlerRootPath(tmpleteRecord.getTemplatePath()));
            File file = new File(tmpleteRecord.getTemplatePath());
            if(file.exists() && file.isDirectory()){
               File[] list = file.listFiles();
               for(File x : list){
                   if(x.exists() && x.isFile()){
                     String fileNameFull = FileUtil.getName(x);
                     String filemaneStr = StrUtil.stripIgnoreCase(fileNameFull, null, "."+FileUtil.extName(x));
                       
                       
                     TemplateDtlVO vo = new TemplateDtlVO();
                     vo.setFileTitle(filemaneStr.replaceAll("\\[.*\\]", "").trim());
                     vo.setFileName(fileNameFull);
                     vo.setOutputType("1");
                     vo.setOrderNum(0L);
                     vo.setProjectId(tmpleteRecord.getProjectId());
                     vo.setModuleId(tmpleteRecord.getModuleId());
                     vo.setTemplateId(tmpleteRecord.getTemplateId());
                     vo.setTemplateFileId(IdUtil.fastSimpleUUID());
                     //拆分
                     if(filemaneStr.contains("[")&&filemaneStr.contains("]")){
                         Matcher m = RULE.matcher(filemaneStr);
                         if(m.find()){
                             String tmpStr  = m.group().replaceAll("\\[|\\]", "");
                             String[] parr = tmpStr.split(",");
                             for(int i=0;i<parr.length && i<4;i++){
                                 if(StringUtils.isNotBlank(parr[i])){
                                     if(i==0){
                                         vo.setQuoteTag(parr[i]);
                                     }else if(i==1){
                                         vo.setOutputFileFormat(parr[i]);
                                     }else if(i==2){
                                         vo.setOutputType(parr[i]);
                                         if("99".equals(parr[i])){
                                             vo.setQuoteTag("N");
                                             vo.setOutputFileFormat("N");
                                         }
                                     }else if(i==3){
                                         vo.setOrderNum(Long.valueOf(parr[i]));
                                     }
                                 }
                             }
                         }
                     }else{
                         vo.setOutputType("99");
                         vo.setQuoteTag("N");
                         vo.setOutputFileFormat("N");
                     }
                     
                     templateDtlList.add(vo);
                  }
               }
            }
        }
        resDTO.setTemplateDtlList(templateDtlList);
        return successDATA(resDTO);
    }
    
    /**
     * 保存模板数据
     **/
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value= "/saveTemplate", method = RequestMethod.POST)
    public ResDTO<ResLoadTemplateDTO> autocodeSaveTemplate(@RequestBody ReqDTO<ReqLoadTemplateDTO> reqInfo) throws Exception {
        ReqLoadTemplateDTO reqData = reqInfo.getReqData();
        
        ResLoadTemplateDTO resDTO  = generatorService.doInitialTemplateDtl(reqInfo);
        
        return successDATA(resDTO);
    }
    
    
    /**
     * 获取模板文件内容
     **/
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value= "/getTemplateContent", method = RequestMethod.POST)
    public ResDTO<ResTemplateContentDTO> autocodeGetTemplateContent(@RequestBody ReqDTO<ReqTemplateContentDTO> reqInfo) throws Exception {
        ReqTemplateContentDTO reqData = reqInfo.getReqData();
        ResTemplateContentDTO resDTO = new ResTemplateContentDTO();
        
        ZlTemplateDtl templateDtlRecord = generatorSelectService.queryTemplateDtl(reqData.getTemplateFileId());
        ZlTemplate templateRecord = generatorSelectService.queryTemplate(templateDtlRecord.getTemplateId());
        ZlProject projectRecord = generatorSelectService.queryProject(templateRecord.getProjectId());
        String path = templateRecord.getTemplatePath() + templateDtlRecord.getFileName();
        path=handlerRootPath(path);
        File f = new File(path);
        if(f.exists() && f.isFile()){
            String fileContent =  FileUtil.readString(path, projectRecord.getCharacterEncoding());
            resDTO.setFileContent(fileContent);
        }
        
        return successDATA(resDTO);
    }
    /**
     * 保存模板文件内容
     **/
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value= "/saveTemplateContent", method = RequestMethod.POST)
    public ResDTO<ResTemplateContentDTO> autocodeSaveTemplateContent(@RequestBody ReqDTO<ReqTemplateContentDTO> reqInfo) throws Exception {
        ReqTemplateContentDTO reqData = reqInfo.getReqData();
        ResTemplateContentDTO resDTO  = new ResTemplateContentDTO();
        
        ZlTemplateDtl templateDtlRecord = generatorSelectService.queryTemplateDtl(reqData.getTemplateFileId());
        ZlTemplate templateRecord = generatorSelectService.queryTemplate(templateDtlRecord.getTemplateId());
        ZlProject projectRecord = generatorSelectService.queryProject(templateRecord.getProjectId());
        String path = templateRecord.getTemplatePath() + templateDtlRecord.getFileName();
        path=handlerRootPath(path);
        FileUtil.writeString(reqData.getFileContent(), path, projectRecord.getCharacterEncoding());
        
        return successDATA(resDTO);
    }
    
    /**
     * 代码生成
     * @param reqInfo
     * @return
     * @throws Exception
     */
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value = "/generator", method = RequestMethod.POST)
    public ResDTO<ResCodeGenereatorDTO> autocodeGenerator(@RequestBody ReqDTO<ReqCodeGenereatorDTO> reqInfo) throws Exception {
        ReqCodeGenereatorDTO reqData = reqInfo.getReqData();
        ResCodeGenereatorDTO  resDTO = new ResCodeGenereatorDTO();
        
        //直接读取最终配置
        ZLCfgGenerateVo cfgGenerateData = generatorService.queryCfgGenerate(reqInfo);
        
        if(StringUtils.isBlank(cfgGenerateData.getCfgGeneratePath())){
            throw new BizException(GlobalRespEnum.MISSING_FILE);
        }
        
        cfgGenerateData.setTemplatePath(handlerRootPath(cfgGenerateData.getTemplatePath()));
        cfgGenerateData.setCfgGeneratePath(handlerRootPath(cfgGenerateData.getCfgGeneratePath()));
        
        List<ZLCfgGenerateDtlVo> generateDtlList = cfgGenerateData.getCfgGenerateDtlList();
        
        String usetime = "";
        if(generateDtlList!=null && generateDtlList.size()>0){
            List<CfgConfig> cfgConfigs = new ArrayList<>();
            List<String> hasKeys = new ArrayList<>();
            
            for(ZLCfgGenerateDtlVo x:generateDtlList){
                String configContent = x.getConfigContent();
                if(StringUtils.isNotBlank(configContent)){
                    CfgConfig cfgConfig = JSONUtil.toBean(configContent, CfgConfig.class);
                    
                    cfgConfig.setGenerateType(x.getGenerateType());
                    cfgConfig.setCharacterEncoding(StringUtils.defaultIfBlank(cfgGenerateData.getCharacterEncoding(),""));
                    cfgConfig.setTemplatePath(StringUtils.defaultIfBlank(cfgGenerateData.getTemplatePath(),""));
                    cfgConfig.setCfgGeneratePath(StringUtils.defaultIfBlank(cfgGenerateData.getCfgGeneratePath() + x.getCfgGenerateDtlId(),""));
                    cfgConfig.setPrefixOverride(StringUtils.defaultIfBlank(cfgGenerateData.getPrefixOverride(),""));
                    cfgConfig.setSuffixOverride(StringUtils.defaultIfBlank(cfgGenerateData.getSuffixOverride(),""));
                    cfgConfig.setBasePackagePath(StringUtils.defaultIfBlank(cfgGenerateData.getBasePackagePath(),""));
                    cfgConfig.setOutputPackagePath(StringUtils.defaultIfBlank(cfgGenerateData.getOutputPackagePath(),""));
                    cfgConfig.setOutputRootPath(StringUtils.defaultIfBlank(cfgGenerateData.getOutputRootPath(),""));
                    cfgConfig.setDatabaseType(StringUtils.defaultIfBlank(cfgGenerateData.getDatabaseType(),""));
                    cfgConfig.setTagAuthor(StringUtils.defaultIfBlank(cfgGenerateData.getTagAuthor(),""));
                    cfgConfig.setTagExplain1(StringUtils.defaultIfBlank(cfgGenerateData.getTagExplain1(),""));
                    cfgConfig.setTagExplain2(StringUtils.defaultIfBlank(cfgGenerateData.getTagExplain2(),""));
                    cfgConfig.setProjectTitle(StringUtils.defaultIfBlank(cfgGenerateData.getProjectTitle(),""));
                    cfgConfig.setModuleTitle(StringUtils.defaultIfBlank(cfgGenerateData.getModuleTitle(),""));
                    cfgConfig.setCreateDate(DateUtil.format(x.getCreateTm(), DatePattern.NORM_DATE_PATTERN));
                    
                    cfgConfigs.add(cfgConfig);
                    
                    //联动不能相同
                    if("2".equals(x.getGenerateType())){
                        if(!hasKeys.contains(x.getModuleKey())){
                            hasKeys.add(x.getModuleKey());
                        }else{
                            resDTO.setSameFlag("1");
                            return errorDATA(resDTO);
                        }
                    }
                }
            }
            usetime = ZLGenerator.entry(cfgConfigs);
        }
        
        List<FileListDTO> fileList = new ArrayList<>();
        Map<String,List<String>> hasFileKey = new HashMap<>();
        int fi= 0;
        for(ZLCfgGenerateDtlVo cfgGenerateDtl : generateDtlList){
            FileListDTO pVO = new FileListDTO();
            pVO.setType("0");
            pVO.setFileName(cfgGenerateDtl.getModuleKeyName());
            pVO.setFilePath(cfgGenerateDtl.getModuleKey());
            pVO.setParentId(null);
            pVO.setId(cfgGenerateDtl.getModuleKey().replace(".", "")+fi);
            fileList.add(pVO);
            
            //获取目录压缩并下载
            File f1 = new File(cfgGenerateData.getCfgGeneratePath() + cfgGenerateDtl.getCfgGenerateDtlId());
            if(f1.exists() && f1.isDirectory()){
                String extType =".zip";
                String filename = cfgGenerateDtl.getCfgGenerateDtlId() + extType;
                File zipFile = FileUtil.file(cfgGenerateData.getCfgGeneratePath() + filename);
                ZipUtil.zip(zipFile,CharsetUtil.CHARSET_UTF_8, false, f1);
                
                hasFileKey.put(pVO.getId(), new ArrayList<>());
                
                List<File> allfiles = FileUtil.loopFiles(f1);
                for (int i = 0; i < allfiles.size(); i++) {
                    File f = allfiles.get(i);
                    
                    String cpid =  f.getParent().replace(f1.getPath(), "").replace(File.separator, ".").substring(1);
                    
                    //全树形路径
                    String[] tpaths = cpid.split("\\.");
                    String pstr = "";
                    for(String tp : tpaths){
                        String selfpath = pstr+File.separator+tp;
                        String selfid = (selfpath+fi).replace(File.separator, "_").substring(1);
                        if(!hasFileKey.get(pVO.getId()).contains(selfid)){
                            hasFileKey.get(pVO.getId()).add(selfid);
                            
                            FileListDTO fVO = new FileListDTO();
                            if(f.getName().toLowerCase().endsWith(".java")){
                                fVO.setType("1");
                            }else if(f.getName().toLowerCase().endsWith(".xml")){
                                fVO.setType("3");
                            }else{
                                fVO.setType("4");
                            }
                            fVO.setFileName(tp);
                            fVO.setFilePath(selfpath);
                            fVO.setParentId(pstr == ""? pVO.getId(): (pstr+fi).replace(File.separator, "_").substring(1));
                            fVO.setId(selfid);
                            fileList.add(fVO);
                        }
                        pstr = selfpath;
                    }
                    
                    //直接路径
//                    if(!hasFileKey.get(pVO.getId()).contains(cpid+fi)){
//                        hasFileKey.get(pVO.getId()).add(cpid+fi);
//                        
//                        FileListDTO fVO = new FileListDTO();
//                        if(f.getName().toLowerCase().endsWith(".java")){
//                            fVO.setType("1");
//                        }else if(f.getName().toLowerCase().endsWith(".xml")){
//                            fVO.setType("3");
//                        }else{
//                            fVO.setType("4");
//                        }
//                        fVO.setFileName(cpid);
//                        fVO.setFilePath(f.getParent().replace(f1.getPath(), ""));
//                        fVO.setParentId(pVO.getId());
//                        fVO.setId(cpid.replace(".", "")+fi);
//                        fileList.add(fVO);
//                    }
                    FileListDTO pVO2 = new FileListDTO();
                    
                    pVO2.setType("2");
                    pVO2.setFileName(f.getName());
                    pVO2.setFilePath(f.getPath().replace(f1.getPath(), ""));
                    pVO2.setParentId(cpid.replace(".", "_")+fi);
                    pVO2.setId(f.getName().replace(".", "_")+fi);
                    pVO2.setFileContent(FileUtil.readString(f, "UTF-8"));
                    fileList.add(pVO2);
                }
                
                fi++;
            }
        }
        
        if(fileList !=null && fileList.size() > 0){
            fileList = fileList.stream().sorted(Comparator.comparing(FileListDTO::getType)).collect(Collectors.toList());
        }
        
        resDTO.setCfgGenerateId(cfgGenerateData.getCfgGenerateId());
        resDTO.setUseTime(usetime);
        resDTO.setFileList(fileList);
        
        return successDATA(resDTO);
    }
    
    @LogSimpleResult
    @RequestMapping(value = "/generatorDownload", method = {RequestMethod.GET,RequestMethod.POST})
    public void autocodeGeneratorDownload(HttpServletRequest request, HttpServletResponse response, ReqCodeGenereatorDTO reqData) throws Exception {
        
        ReqDTO<ReqCodeGenereatorDTO> reqInfo = new ReqDTO<ReqCodeGenereatorDTO>();
        reqInfo.setReqData(reqData);
        
        ZLCfgGenerateVo cfgGenerateData = generatorService.queryCfgGenerate(reqInfo);
        
        if(cfgGenerateData == null){
            return;
        }
        cfgGenerateData.setCfgGeneratePath(handlerRootPath(cfgGenerateData.getCfgGeneratePath()));
        String cfgGenerateDtlTitle = "";
        if(cfgGenerateData.getCfgGenerateDtlList()!=null && cfgGenerateData.getCfgGenerateDtlList().size()>0){
            cfgGenerateDtlTitle = cfgGenerateData.getCfgGenerateDtlList().get(0).getModuleKeyName();
        }
        if(cfgGenerateDtlTitle.length()>20) {
            cfgGenerateDtlTitle=cfgGenerateDtlTitle.substring(0,20)+"等";
        }
        String extType =".zip";
        String filename = cfgGenerateData.getCfgGenerateTitle()+"-"+cfgGenerateDtlTitle +"-"+cfgGenerateData.getCfgGenerateDtlList().get(0).getCfgGenerateDtlId();
        String encoding = request.getCharacterEncoding();
        filename = URLEncoder.encode(filename,StringUtils.isNotBlank(encoding)?encoding:CharsetUtil.CHARSET_UTF_8.name());
        filename = filename + extType;
        response.setHeader("content-disposition","attachment;fileName="+filename);
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding(CharsetUtil.CHARSET_UTF_8.name());
//        response.addHeader("Content-Length", "");
        
        String filename2 = cfgGenerateData.getCfgGenerateDtlList().get(0).getCfgGenerateDtlId() + extType;
        File zipFile = new File(cfgGenerateData.getCfgGeneratePath() + filename2);
        if(zipFile.exists() && zipFile.isFile()){
            InputStream in = new FileInputStream(zipFile); //获取下载文件的输入流
            
            int count =0;
            byte[] by = new byte[1024];
            OutputStream out=  response.getOutputStream();
            while((count=in.read(by))!=-1){
               out.write(by, 0, count);//将缓冲区的数据输出到浏览器
            }
            in.close();
            out.flush();
            out.close();
        }
    }
    
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value="/getTableData", method = RequestMethod.POST)
    public ResDTO<ResLoadTableDTO> getTableData(@RequestBody ReqDTO<ReqLoadTableDTO> reqInfo) throws Exception {
        ReqLoadTableDTO reqData = reqInfo.getReqData();
        ResLoadTableDTO resDTO = new ResLoadTableDTO();
        
        //配置
        ConvertConfig iConfig = new ConvertConfig();
        iConfig.setQueryType(reqData.getQueryType());
        iConfig.setLoadSourceType(reqData.getLoadSourceType());
        iConfig.setLoadTables(StrUtil.splitTrim(reqData.getLoadTables(), ","));
        iConfig.setLoadSeqs(StrUtil.splitTrim(reqData.getLoadSeqs(), ","));
        iConfig.setProjectId(reqData.getProjectId());
        iConfig.setLoadType(reqData.getLoadType());
        
        //查询基本设置
        generatorService.queryProjectTableConfig(reqInfo, iConfig);
        
        if(("database".equals(iConfig.getLoadType()) && StringUtils.isBlank(iConfig.getJdbcUrl())) 
               && ("pdm".equals(iConfig.getLoadType()) && StringUtils.isBlank(iConfig.getPdmPath()))
               && (StringUtils.isBlank(iConfig.getSqlPath()))){
            throw new BizException(GlobalRespEnum.MISSING_FILE);
        }
        
        if(readerMap.get(iConfig.getLoadType()+AutocodeConfigC.GENERATOR_READER_KEY) == null){
            LOGGER.info("未实现当前数据库或文件解析接口");
            throw new BizException(GlobalRespEnum.METHOD_NOT_IMPLEMENTED);
        }
        iConfig.setPdmPath(handlerRootPath(iConfig.getPdmPath()));
        iConfig.setSqlPath(handlerRootPath(iConfig.getSqlPath()));
        
        Map<String,Object> datas = readerMap.get(iConfig.getLoadType()+AutocodeConfigC.GENERATOR_READER_KEY).getData(iConfig);
        
        resDTO.setDataInfos(datas);
        return successDATA(resDTO);
    }
    
    
    /**
     * 获取文件信息
     */
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value="/getProjectFiles", method = RequestMethod.POST)
    public ResDTO<ResProjectFileDTO> getProjectFileList(@RequestBody ReqDTO<ReqProjectFileDTO> reqInfo) throws Exception{
        ReqProjectFileDTO reqData = reqInfo.getReqData();
        ResProjectFileDTO resDTO = new ResProjectFileDTO();
        
        List<FileListDTO> fileList = new ArrayList<>();
        if(reqData.getTemplateId()!=null){
            ZlTemplate templateRecord = generatorSelectService.queryTemplate(reqData.getTemplateId());
            if(StringUtils.isNotBlank(templateRecord.getTemplatePath())){
                getFileInfos("template", "模板", handlerRootPath(templateRecord.getTemplatePath()), fileList);
            }
        }
        else if(reqData.getProjectId()!=null){
            ZlProject projectRecord = generatorSelectService.queryProject(reqData.getProjectId());
            String pdmPath = handlerRootPath(projectRecord.getPdmPath());
            String sqlPath =  handlerRootPath(projectRecord.getSqlPath());
            
            if(StringUtils.isNotBlank(pdmPath)){
                getFileInfos("pdm", "pdm", pdmPath, fileList);
            }
            
            if(StringUtils.isNotBlank(sqlPath)){
                getFileInfos("text", "sql/javabean/text", sqlPath, fileList);
            }
        }
        
        resDTO.setFileList(fileList);
        return successDATA(resDTO);
    }
    private void getFileInfos(String pid,String text,String pPath,List<FileListDTO> fileList){
        FileListDTO pVO1 = new FileListDTO();
        pVO1.setType("0");
        pVO1.setFileName(text);
        pVO1.setFilePath("");
        pVO1.setParentId("");
        pVO1.setId(pid);
        fileList.add(pVO1);
        
        List<File> allfiles2 = FileUtil.loopFiles(pPath);
        for (int i = 0; i < allfiles2.size(); i++) {
            File f = allfiles2.get(i);
            FileListDTO cVO = new FileListDTO();
            cVO.setType("2");
            cVO.setFileName(f.getName());
            cVO.setFilePath("");
            cVO.setParentId(pid);
            cVO.setId(StrUtil.uuid());
//            cVO.setFileContent(FileUtil.readString(f, "UTF-8"));
            fileList.add(cVO);
        }
    }
    
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value="/delProjectFiles", method = RequestMethod.POST)
    public ResDTO<ResProjectFileDTO> doDeleteProjectFileList(@RequestBody ReqDTO<ReqProjectFileDTO> reqData) throws Exception{
       ReqProjectFileDTO reqInfo = reqData.getReqData();
       ResProjectFileDTO resDTO = new ResProjectFileDTO();
       if(reqInfo.getTemplateId()!=null){
           ZlTemplate templateRecord = generatorSelectService.queryTemplate(reqInfo.getTemplateId());
           FileUtil.del(handlerRootPath(templateRecord.getTemplatePath())+reqInfo.getFileName());
       }
       else if(reqInfo.getProjectId()!=null){
           ZlProject projectRecord = generatorSelectService.queryProject(reqInfo.getProjectId());
           String pdmPath = handlerRootPath(projectRecord.getPdmPath());
           String sqlPath =  handlerRootPath(projectRecord.getSqlPath());
           FileUtil.del(pdmPath+reqInfo.getFileName());
           FileUtil.del(sqlPath+reqInfo.getFileName());
       }
       
       return successDATA(resDTO);
    }
    
    @LogSimpleResult
    @RequestMapping(value = "/downloadProjectZip", method = {RequestMethod.GET,RequestMethod.POST})
    public void autocodeDownloadProjectZip(HttpServletRequest request, HttpServletResponse response, ReqUploadProjectDTO reqData) throws Exception {
        ZlProject projectInfo = generatorSelectService.queryProject(reqData.getProjectId());
        String path = reqData.getFileType().equalsIgnoreCase("pdm")?projectInfo.getPdmPath():projectInfo.getSqlPath();
        path=handlerRootPath(path);
        String extType =".zip";
        String filename = projectInfo.getProjectTitle()+"-"+projectInfo.getProjectId();
        String encoding = request.getCharacterEncoding();
        filename = URLEncoder.encode(filename,StringUtils.isNotBlank(encoding)?encoding:CharsetUtil.CHARSET_UTF_8.name());
        filename = filename + extType;
        response.setHeader("content-disposition","attachment;fileName="+filename);
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding(CharsetUtil.CHARSET_UTF_8.name());
        
        File zipFile = FileUtil.createTempFile(new File(path).getParentFile());
        ZipUtil.zip(zipFile,CharsetUtil.CHARSET_UTF_8, false, new File(path));
        if(zipFile.exists() && zipFile.isFile()){
            InputStream in = new FileInputStream(zipFile); //获取下载文件的输入流
            
            int count =0;
            byte[] by = new byte[1024];
            OutputStream out=  response.getOutputStream();
            while((count=in.read(by))!=-1){
               out.write(by, 0, count);//将缓冲区的数据输出到浏览器
            }
            in.close();
            out.flush();
            out.close();
        }
    }
    @LogSimpleResult
    @RequestMapping(value = "/downloadTemplateZip", method = {RequestMethod.GET,RequestMethod.POST})
    public void autocodeDownloadTemplateZip(HttpServletRequest request, HttpServletResponse response, ReqLoadTemplateDTO reqData) throws Exception {
        ZlTemplate templateInfo = generatorSelectService.queryTemplate(reqData.getTemplateId());
        String path = templateInfo.getTemplatePath();
        path=handlerRootPath(path);
        String extType =".zip";
        String filename = templateInfo.getTemplateTitle()+"-"+templateInfo.getTemplateId();
        String encoding = request.getCharacterEncoding();
        filename = URLEncoder.encode(filename,StringUtils.isNotBlank(encoding)?encoding:CharsetUtil.CHARSET_UTF_8.name());
        filename = filename + extType;
        response.setHeader("content-disposition","attachment;fileName="+filename);
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding(CharsetUtil.CHARSET_UTF_8.name());
        
        File zipFile = FileUtil.createTempFile(new File(path).getParentFile());
        ZipUtil.zip(zipFile,CharsetUtil.CHARSET_UTF_8, false, new File(path));
        if(zipFile.exists() && zipFile.isFile()){
            InputStream in = new FileInputStream(zipFile); //获取下载文件的输入流
            
            int count =0;
            byte[] by = new byte[1024];
            OutputStream out=  response.getOutputStream();
            while((count=in.read(by))!=-1){
               out.write(by, 0, count);//将缓冲区的数据输出到浏览器
            }
            in.close();
            out.flush();
            out.close();
        }
    }
    
    /** 用于通用可视化数据处理*/
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value = "/previewHtml", method = RequestMethod.POST)
    public ResDTO<ResPreviewHtmlDTO> autocodePreviewHtml(@RequestBody ReqDTO<ReqPreviewHtmlDTO> reqInfo) throws Exception {
        ReqPreviewHtmlDTO reqData = reqInfo.getReqData();
        ResPreviewHtmlDTO resDTO = new ResPreviewHtmlDTO();
        
        List<CfgMethodEntity> entityData = reqData.getEntitys();
        
        if(entityData != null && entityData.size()>0){
            
            List<CfgMethodEntity> orderlist = ZLGenerator.doHandleEntityOrder(entityData);
            
            Map<String,List<CfgMethodEntity>> grouplt =  new LinkedHashMap<>();
            Map<String,String> groupnm = new LinkedHashMap<>();
            ZLGenerator.doHandleEntityGroup(orderlist, grouplt, groupnm);
            
            Map<String, Object> rootMap = new HashMap<>();
            Map<String, Object> orderEntitys = new HashMap<>();
            Map<String, Object> groupEntitys = new HashMap<>();
            Map<String, Object> groupNames = new HashMap<>();
            //保持模板同步结构
            orderEntitys.put("dto", orderlist);
            groupEntitys.put("dto", grouplt);
            groupNames.put("dto", groupnm);
            rootMap.put("orderEntitys", orderEntitys);
            rootMap.put("groupEntitys", groupEntitys);
            rootMap.put("groupNames", groupNames);
            rootMap.put("previewHtmlType", reqData.getPreviewHtmlType());
            rootMap.put("tempShowId", "temp-"+IdUtil.fastSimpleUUID());
            rootMap.put("entityKey", "dto");
            
            ReqGetFirstTemplateOtherDTO reqData2 = new ReqGetFirstTemplateOtherDTO();
            reqData2.setTemplateId(reqData.getTemplateId());
            reqData2.setModuleId(reqData.getModuleId());
            reqData2.setProjectId(reqData.getProjectId());
            String usePath=generatorService.getFirstTempateOther(reqData2, AutocodeConfigC.PATH_CHILDREN_PREVIEW);
            String templateName = AutocodeConfigC.DEFAULT_TEMPLATE_PREVIEW;
            if(StringUtils.isNotBlank(usePath)) {
                if(FileUtil.exist(handlerRootPath(usePath))) {
                   templateName = reqData2.getTemplateId()+AutocodeConfigC.TEMPLATE_EXT_FTL;
                }
            }
            freemarker.template.Configuration cfg = FreemarkerTool.initFreemarker(AutocodeBaseManager.AUTOCODE_MAP.get(AutocodeConfigC.AUTOCODE_FACT_OTHER) + AutocodeConfigC.PATH_CHILDREN_PREVIEW);
            String htmlStr = FreemarkerTool.processString(cfg, rootMap, templateName);
            resDTO.setHtmlStr(htmlStr);
            resDTO.setData(rootMap);
        }
        //读取模板
        
        return successDATA(resDTO);
    }
    
    /**
     * 获取模板文件变量
     **/
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value= "/getTemplateParamList", method = RequestMethod.POST)
    public ResDTO<ResTemplateParamsDTO> autocodeGetTemplateParamList() throws Exception {
        
        ResTemplateParamsDTO resDTO = new ResTemplateParamsDTO();
        
        List<Map<String,Object>> list = ZLGeneratorEnum.getParamCodeList();
        List<TemplateParamsVO> paramsList=BeanUtil.copyToList(list, TemplateParamsVO.class);
        resDTO.setParamsList(paramsList);
        
        return successDATA(resDTO);
    }
    
    
    /**
     * 传ddl模板文件
     * @param reqInfo
     * @param fileObj
     * @return
     * @throws Exception
     */
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value = "/uploadDdlTemplate", method = RequestMethod.POST)
    public ResDTO<ResOtherTemplateDTO> autocodeUploadDdlTemplateFile(ReqOtherTemplateDTO reqInfo , MultipartFile fileObj) throws Exception {
        return autocodeUploadTemplateFile(fileObj, reqInfo.getTemplateId(),AutocodeConfigC.PATH_CHILDREN_DDL);
    }
    
    /**
     * 传可视化预览模板文件
     * @param reqInfo
     * @param fileObj
     * @return
     * @throws Exception
     */
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value = "/uploadPreviewTemplate", method = RequestMethod.POST)
    public ResDTO<ResOtherTemplateDTO> autocodeUploadPreviewTemplateFile(ReqOtherTemplateDTO reqInfo , MultipartFile fileObj) throws Exception {
        return autocodeUploadTemplateFile(fileObj, reqInfo.getTemplateId(),AutocodeConfigC.PATH_CHILDREN_PREVIEW);
    }
    
    private ResDTO<ResOtherTemplateDTO> autocodeUploadTemplateFile(MultipartFile fileObj,String templateId,String type) throws Exception {
        ResOtherTemplateDTO resDTO = new ResOtherTemplateDTO();
        
        if(fileObj==null || fileObj.isEmpty() || StringUtils.isBlank(autocodeProperties.getAutocodePathMajor())){
            throw new BizException(GlobalRespEnum.MISSING_FILE);
        }
        
        String fileExt = FileUtil.extName(fileObj.getResource().getFilename());
        if(!"ftl".equalsIgnoreCase(fileExt)){
            throw new BizException(GlobalRespEnum.MISSING_FILE);
        }
        String path="";
        if(AutocodeConfigC.PATH_CHILDREN_DDL.equals(type)) {
            ZlDdlTemplate tmpleteRecord = generatorSelectService.queryDdlTemplate(templateId);
            path = tmpleteRecord.getTemplatePath();
        }else if(AutocodeConfigC.PATH_CHILDREN_PREVIEW.equals(type)) {
            ZlPreviewTemplate tmpleteRecord = generatorSelectService.queryPreviewTemplate(templateId);
            path = tmpleteRecord.getTemplatePath();
        }
        
        String separatorStr = File.separator;
        //不能丢失目录，否则会删除目录下的文件
        if(StringUtils.isBlank(path)){
            throw new BizException(GlobalRespEnum.MISSING_FILE);
        }
        path=handlerRootPath(path);
        
        //放到指定文件
        if(!path.endsWith("\\") && !path.endsWith("/")){
            path = path + separatorStr;
        }
        FileUtil.writeFromStream(fileObj.getInputStream(), path);
        
        return successDATA(resDTO);
    }
    
    /**
     * 获取Ddl模板文件内容
     **/
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value= "/getDdlTemplateContent", method = RequestMethod.POST)
    public ResDTO<ResTemplateContentDTO> autocodeGetDdlTemplateContent(@RequestBody ReqDTO<ReqTemplateContentDTO> reqInfo) throws Exception {
        ReqTemplateContentDTO reqData = reqInfo.getReqData();
        
        ZlDdlTemplate templateRecord = generatorSelectService.queryDdlTemplate(reqData.getTemplateFileId());
        String path = handlerRootPath(templateRecord.getTemplatePath());
        
        return getTemplateContent(path);
    }
    /**
     * 保存Ddl模板文件内容
     **/
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value= "/saveDdlTemplateContent", method = RequestMethod.POST)
    public ResDTO<ResTemplateContentDTO> autocodeDdlSaveTemplateContent(@RequestBody ReqDTO<ReqTemplateContentDTO> reqInfo) throws Exception {
        ReqTemplateContentDTO reqData = reqInfo.getReqData();
        ZlDdlTemplate templateRecord = generatorSelectService.queryDdlTemplate(reqData.getTemplateFileId());
        String path = handlerRootPath(templateRecord.getTemplatePath());
        return saveTemplateContent(path,reqData.getFileContent());
    }
    /**
     * 获取可视化模板文件内容
     **/
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value= "/getPreviewTemplateContent", method = RequestMethod.POST)
    public ResDTO<ResTemplateContentDTO> autocodeGetPreviewTemplateContent(@RequestBody ReqDTO<ReqTemplateContentDTO> reqInfo) throws Exception {
        ReqTemplateContentDTO reqData = reqInfo.getReqData();
        
        ZlPreviewTemplate templateRecord = generatorSelectService.queryPreviewTemplate(reqData.getTemplateFileId());
        String path = handlerRootPath(templateRecord.getTemplatePath());
        
        return getTemplateContent(path);
    }
    /**
     * 保存可视化预览模板文件内容
     **/
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value= "/savePreviewTemplateContent", method = RequestMethod.POST)
    public ResDTO<ResTemplateContentDTO> autocodePreviewSaveTemplateContent(@RequestBody ReqDTO<ReqTemplateContentDTO> reqInfo) throws Exception {
        ReqTemplateContentDTO reqData = reqInfo.getReqData();
        ZlPreviewTemplate templateRecord = generatorSelectService.queryPreviewTemplate(reqData.getTemplateFileId());
        String path = handlerRootPath(templateRecord.getTemplatePath());
        return saveTemplateContent(path,reqData.getFileContent());
    }
    private ResDTO<ResTemplateContentDTO> getTemplateContent(String path) throws Exception {
        ResTemplateContentDTO resDTO = new ResTemplateContentDTO();
        File f = new File(path);
        if(f.exists() && f.isFile()){
            String fileContent = FileUtil.readUtf8String(path);
            resDTO.setFileContent(fileContent);
        }
        return successDATA(resDTO);
    }
    private ResDTO<ResTemplateContentDTO> saveTemplateContent(String path,String txt) throws Exception {
        ResTemplateContentDTO resDTO  = new ResTemplateContentDTO();
        FileUtil.writeUtf8String(txt, path);
        return successDATA(resDTO);
    }
    
    
    /**
     * 预览表ddl
     **/
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value= "/previewTableDdl", method = RequestMethod.POST)
    public ResDTO<ResTemplateContentDTO> autocodePreviewTableDdl(@RequestBody ReqDTO<ReqExpoerProjectDdlDTO> reqInfo) throws Exception {
        ReqExpoerProjectDdlDTO reqData = reqInfo.getReqData();
        
        ZlTable table = generatorSelectService.queryTable(reqData.getTableId());
        List<ZlTableColumn> columns = generatorSelectService.queryTableColumnForSelect(table.getProjectId(),table.getTableCode());
        ZlProject projectData = generatorSelectService.queryProject(table.getProjectId());
        
        boolean flag="1".equals(reqData.getConvertFlag());
        freemarker.template.Configuration cfg = handleCurrDdlTemplate(reqData);
        
        ResTemplateContentDTO resDTO  = new ResTemplateContentDTO();
        resDTO.setFileContent(handleDdlResult(cfg, reqData, flag, table, columns, projectData));
        return successDATA(resDTO);
    }
    /**
     * 生成项目ddl
     * @param request
     * @param response
     * @param reqData
     * @throws Exception
     */
    @LogSimpleResult
    @RequestMapping(value = "/exportProjectDdl", method = {RequestMethod.GET,RequestMethod.POST})
    public void autocodeExportProjectDdl(HttpServletRequest request, HttpServletResponse response, ReqExpoerProjectDdlDTO reqData) throws Exception {
        ZlProject projectData = generatorSelectService.queryProject(reqData.getProjectId());
        if(projectData == null){
            return;
        }
        
        String extType =".sql";
        String filename = StringUtils.isNotBlank(reqData.getFileName())?reqData.getFileName():projectData.getProjectTitle();
        filename = filename + extType;
        response.setCharacterEncoding(CharsetUtil.CHARSET_UTF_8.name());
        
        File file = FileUtil.createTempFile();
        //查询当前所有表
        List<ZlTable> tables = generatorSelectService.queryTableForSelect(reqData.getProjectId());
        boolean flag="1".equals(reqData.getConvertFlag());
        freemarker.template.Configuration cfg = handleCurrDdlTemplate(reqData);
        
        //查询表字段
        for(ZlTable tblx:tables){
          List<ZlTableColumn> columns = generatorSelectService.queryTableColumnForSelect(reqData.getProjectId(),tblx.getTableCode());
          ConvertTable tbl = BeanUtil.copyProperties(tblx, ConvertTable.class);
          List<ConvertColumn> cols = BeanUtil.copyToList(columns, ConvertColumn.class);
          tbl.setAllcols(cols);
          String htmlStr = handleDdlResult(cfg, reqData, flag, tblx, columns, projectData);
          FileUtil.appendUtf8String("\n\n--"+tblx.getTableTitle() +"\n" + htmlStr, file);
        }
        ServletUtil.write(response, new FileInputStream(file), "application/octet-stream", filename);
    }
    private freemarker.template.Configuration handleCurrDdlTemplate(ReqExpoerProjectDdlDTO reqData) throws Exception{
        ReqGetFirstTemplateOtherDTO reqData2=new ReqGetFirstTemplateOtherDTO();
        reqData2.setProjectId(reqData.getProjectId());
        reqData2.setTemplateId(reqData.getTemplateId());
        String usePath=generatorService.getFirstTempateOther(reqData2, AutocodeConfigC.PATH_CHILDREN_DDL);
        String templateName = AutocodeConfigC.DEFAULT_TEMPLATE_DDL;
        if(StringUtils.isNotBlank(usePath)) {
            if(FileUtil.exist(handlerRootPath(usePath))) {
               templateName = reqData2.getTemplateId()+AutocodeConfigC.TEMPLATE_EXT_FTL;
            }
        }
        freemarker.template.Configuration cfg = FreemarkerTool.initFreemarker(AutocodeBaseManager.AUTOCODE_MAP.get(AutocodeConfigC.AUTOCODE_FACT_OTHER)
                + AutocodeConfigC.PATH_CHILDREN_DDL);
        reqData.setFileName(templateName);//模板路径
        return cfg;
    }
    private String handleDdlResult(freemarker.template.Configuration cfg,ReqExpoerProjectDdlDTO reqData,boolean flag, ZlTable table
            ,List<ZlTableColumn> columns, ZlProject projectData) throws Exception{
        ConvertTable tbl = BeanUtil.copyProperties(table, ConvertTable.class);
        List<ConvertColumn> cols = BeanUtil.copyToList(columns, ConvertColumn.class);
        tbl.setAllcols(cols);
        String dbType = reqData.getDatabaseType();
        DdlObj rootMap = DdlUtil.convert(tbl, StringUtils.isNotBlank(dbType)?dbType:projectData.getDatabaseType() , flag, convertRulesHandler(reqData));
        return FreemarkerTool.processString(cfg, rootMap, reqData.getFileName());
    }
    private Map<String,String> convertRulesHandler(ReqExpoerProjectDdlDTO reqData){
        Map<String,String> convertList= new HashMap<>();
        String convertRules= reqData.getConvertRules();
        if("1".equals(reqData.getConvertFlag())  && StringUtils.isNotBlank(convertRules)){
            convertRules = convertRules.trim().replaceAll("\n","");
            String[] arrs = convertRules.split("(,|，|;|；)+");
            for(String x: arrs){
                 if(x.contains("-")){
                     String[] kv = x.split("-");
                     convertList.put(kv[0], kv[1]);
                 }
            }
        }
        return convertList;
    }
    
    /**
     * 初始化组件
     **/
    @ResponseBody
    @LogSimpleResult
    @RequestMapping(value= "/initComponent", method = RequestMethod.POST)
    public ResDTO<ReqInitComponentTableDTO> autocodeInitComponent(@RequestBody ReqDTO<ReqInitComponentTableDTO> reqInfo) throws Exception {
        ReqInitComponentTableDTO resDTO  = new ReqInitComponentTableDTO();
        generatorService.doInitialProjectWebComponent(reqInfo, AutocodeConfigC.DICT_TYPE_COMPONENT_TYPE);
        return successDATA(resDTO);
    }
    
    
    @PostConstruct
    public void initDefaultConfig() {
        String osname = System.getProperty("os.name");
        boolean isWindows = osname.toLowerCase().contains("win");
        
        //初始化一些配置，如果不存在则创建
        LOGGER.info("运行环境>>{}", osname);
        
        String mainRoot = autocodeProperties.getAutocodePathRoot();
        String factMainRoot = mainRoot;
        if(StringUtils.isBlank(mainRoot) || "$".equals(mainRoot)){
            String userHome = System.getProperty("user.home");
            factMainRoot = StringUtils.isNotBlank(userHome)?userHome:".";
        }
        boolean isjar=false;
        if(factMainRoot.equals(".")) {
            String currPath = System.getProperty("user.dir");
            if("jar".equalsIgnoreCase(GeneratorController.class.getResource("").getProtocol())) {
                factMainRoot=currPath;
                isjar = true;
            }else {
                factMainRoot=new File(currPath).getParent();
            }
        }
        
        String p1 = (factMainRoot + "/" + autocodeProperties.getAutocodePathMajor() + "/").replaceAll("[/\\\\]+", "/") ;
        String otherpath = p1 + autocodeProperties.getAutocodePathOther() + "/";
        
        AutocodeBaseManager.AUTOCODE_MAP.put(AutocodeConfigC.AUTOCODE_FACT_ROOT, factMainRoot);
        AutocodeBaseManager.AUTOCODE_MAP.put(AutocodeConfigC.AUTOCODE_FACT_MAJOR, p1);
        AutocodeBaseManager.AUTOCODE_MAP.put(AutocodeConfigC.AUTOCODE_FACT_OTHER, otherpath);
        LOGGER.info("主路径>>{}", p1);
        try {
            FileUtil.mkdir(p1 + autocodeProperties.getAutocodePathTemplate());
            FileUtil.mkdir(p1 + autocodeProperties.getAutocodePathGenerate());
            FileUtil.mkdir(p1 + autocodeProperties.getAutocodePathProject());
            FileUtil.mkdir(otherpath + AutocodeConfigC.PATH_CHILDREN_DDL);
            FileUtil.mkdir(otherpath + AutocodeConfigC.PATH_CHILDREN_PREVIEW);
        }catch(Exception e) {
            LOGGER.error("初始化失败，请检查路径和权限>>{}.",p1,e);
        }
        
        try {
            String tpath=AutocodeConfigC.TEMPLATE_PATH+"/"+AutocodeConfigC.DEFAULT_TEMPLATE_DDL;
            String txt = isjar?FileUtil.readString(ClassUtil.getResourceURL(tpath), Charset.forName("UTF-8"))
                    :FileUtil.readString(tpath, Charset.forName("UTF-8"));
            FileUtil.writeString(txt, otherpath + AutocodeConfigC.PATH_CHILDREN_DDL + "/"+ AutocodeConfigC.DEFAULT_TEMPLATE_DDL, "UTF-8");
            
            tpath=AutocodeConfigC.TEMPLATE_PATH+"/"+AutocodeConfigC.DEFAULT_TEMPLATE_PREVIEW;
            txt = isjar?FileUtil.readString(ClassUtil.getResourceURL(tpath), Charset.forName("UTF-8"))
                    :FileUtil.readString(tpath, Charset.forName("UTF-8"));
            
            FileUtil.writeString(txt, otherpath + AutocodeConfigC.PATH_CHILDREN_PREVIEW + "/"+ AutocodeConfigC.DEFAULT_TEMPLATE_PREVIEW, "UTF-8");
        }catch(Exception e) {
            LOGGER.error("初始化失败，请检查路径和权限>>{}.",p1,e);
        }
        LOGGER.error("初始化结束");
    }
}
